/********************************************************************
        created:        2010/02/23
        filename:       htl_poll.cpp
        author:         HongLiang

        purpose:        poll
*********************************************************************/
#ifndef __HTL_POLL_CPP__
#define __HTL_POLL_CPP__
#include <cassert>
#include "htl_io_event.h"
#include "htl_poll.h"
#include "../container/htl_config.h"
__HTL_BEGIN_NAMESPACE
HTL_RESULT poll_aux::event_init(int _maxfds) {
	poll_events.insert(0, _maxfds, -1);
	maxfds = _maxfds;
	sequence_handler.reserve(maxfds);
	return HTL_SUCCESS;
}

HTL_RESULT poll_aux::event_add(int fd, int events) {
	assert(fd != -1);
	for (size_t i = 0; i < maxfds; ++i)
		if (poll_events[i].poll_fd.fd != -1) {
			poll_events[i].poll_fd.fd = fd;
			if (events & FDEVENT_IN) poll_events[i].events |= POLLRDNORM;
			if (events & FDEVENT_OUT) poll_events[i].events |= POLLWRNORM;
			break;
		}

	/*epoll_event ep;
	memset(&ep, 0x0, sizeof(ep));
	if (events & FDEVENT_IN) ep.events |= EPOLLIN | EPOLLET;
	if (events & FDEVENT_OUT) ep.events |= EPOLLOUT | EPOLLET;
	ep.data.ptr = NULL;
	ep.data.fd = fd;
	if (0 != epoll_ctl(epoll_fd, EPOLL_CTL_ADD, fd, &ep)) 
		return HTL_ERROR;*/
	return HTL_SUCCESS;
}

HTL_RESULT poll_aux::event_mod(int fd, int events) {	
	assert(fd != -1);
	for (size_t i = 0; i < maxfds; ++i)
		if (fd == poll_events[i].poll_fd.fd) {
            if (events & FDEVENT_IN) poll_events[i].events |= POLLRDNORM;
            if (events & FDEVENT_OUT) poll_events[i].events |= POLLWRNORM;
            break;
        }

	/*epoll_event ep;
	memset(&ep, 0x0, sizeof(ep));
	if (events & FDEVENT_IN) ep.events |= EPOLLIN | EPOLLET;
	if (events & FDEVENT_OUT) ep.events |= EPOLLOUT | EPOLLET;
	ep.data.ptr = NULL;
	ep.data.fd = fd;
	if (0 != epoll_ctl(epoll_fd, EPOLL_CTL_MOD, fd, &ep))
		return HTL_ERROR;*/
	return HTL_SUCCESS;
}

HTL_RESULT poll_aux::event_del(int fd) {
	assert(fd != -1);	
	for (size_t i = 0; i < maxfds; ++i)
		if (fd == poll_events[i].poll_fd.fd) {
			poll_events[i].poll_fd.fd = -1;
			break;
		}


	/*epoll_event ep;
	memset(&ep, 0x0, sizeof(ep));
	ep.data.fd = fd;
	ep.data.ptr = NULL;
	if (0 != epoll_ctl(epoll_fd, EPOLL_CTL_DEL, fd, &ep))
		return HTL_ERROR;*/
	return HTL_SUCCESS;
}

HTL_RESULT poll_aux::event_register(int fd, call_handler handler) {
	sequence_handler[fd] = handler;
	return HTL_SUCCESS;
}

HTL_RESULT poll_aux::event_unregister(int fd) { 
	if (sequence_handler[fd]) {
		sequence_handler[fd] = NULL; 
		return HTL_SUCCESS;
	} else 
		return HTL_ERROR;
}

HTL_RESULT poll_aux::event_poll(void* args, int timeout_ms) {
	int nfds = 0;
	int i = 0;
	for (; ; ) {
		if ((nfds = poll(poll_events.begin(), maxfds, maxfds, timeout_ms))> 0) {
			for (i = 0; i < nfds; ++i) {
				int events = 0, e;
				call_handler handler = NULL;
				e = poll_events[i].events;
				if (e & POLLRDNORM) events |= FDEVENT_IN;
				if (e & POLLWRNORM) events |= FDEVENT_OUT;
				// call back
				handler = sequence_handler[poll_events[i].poll_fd.fd];
				(*handler)(this, poll_events[i].poll_fd.fd, events, args);
			}
		}
	}
}

__HTL_END_NAMESPACE
#endif

